package com.ce.util.security;
import java.io.*;
import java.security.*;
import java.security.spec.*;
import java.security.interfaces.*;
import java.math.*;

/* add by lixiandi */
public class Sign {
  public Sign() {
  }
public static byte[][] GenerateKeyPair()
	{
		byte[][] MixKey = new byte[4][];
		try{
			System.out.println("Generating a key pair.....");
			//获取密钥算法名称
			KeyPairGenerator keyGen=KeyPairGenerator.getInstance("RSA");
			//初始化密钥对产生器
			keyGen.initialize(1024,new SecureRandom());
			//产生密钥对
			KeyPair pair=keyGen.generateKeyPair();
			//获得公钥对象
			PublicKey pub=pair.getPublic();
			//获得私钥对象
			PrivateKey priv=pair.getPrivate();
			//获得公钥对象的DER编码
			MixKey[0]= pub.getEncoded();
			//获得私钥对象的DER编码
			MixKey[1]= priv.getEncoded();
			//获取组成公钥的模数和指数
			RSAPublicKey Temp = (RSAPublicKey)pub;
			MixKey[2] = Temp.getModulus().toByteArray();
			MixKey[3] = Temp.getPublicExponent().toByteArray();
		}
		catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}
		return MixKey;
	}

	public static boolean SaveKeyDer(byte[] pubKey, byte[] privKey, String ID)
	{
		try{
			FileOutputStream fileOut=new FileOutputStream("PublicKey_"+ID);
			fileOut.write(pubKey);
			fileOut.close();
			fileOut=new FileOutputStream("privateKey_"+ID);
			fileOut.write(privKey);
			fileOut.close();
		}
		catch(Exception e)
		{
			e.printStackTrace();
			return false;
		}
		return true;
	}

	public static boolean SavePubKeyForNet(byte[] Modulus, byte[] Exponent, String ID)
	{
		try{
			byte[] temp = new byte[Modulus.length-1];

     			for (int j=0;j<Modulus.length-1;j++)
     			{
     				temp[j] = Modulus[j+1];
     			}
     			FileOutputStream fileOut=new FileOutputStream("PubKey_ForNet_"+ID);
			fileOut.write(Exponent);
			fileOut.write(temp);
			fileOut.close();
		}
		catch(Exception e)
		{
			e.printStackTrace();
			return false;
		}
		return true;
	}

	public static String SignData(String ID, String src )
	{
		byte[] SignedContext = null;

		try{
			FileInputStream fis = new FileInputStream("privateKey_"+ID);
	        	byte[] EncodedprivKey = new byte[fis.available()];
	        	fis.read(EncodedprivKey);
	        	fis.close();

	        	byte[] Context = src.getBytes();

			PKCS8EncodedKeySpec privKeySpec=new PKCS8EncodedKeySpec(EncodedprivKey);
			KeyFactory keyFactory=KeyFactory.getInstance("RSA");
			PrivateKey privKey=keyFactory.generatePrivate(privKeySpec);
			Signature rsa=Signature.getInstance("SHA1withRSA");
			rsa.initSign(privKey);
			for (int i=0;i<Context.length;i++)
				rsa.update(Context[i]);
			SignedContext=base64enc(rsa.sign());
		}
		catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}
		return new String(SignedContext);

	}

	public static byte[] SignData1(byte[] EncodedprivKey, byte[] Context )
	{
		byte[] SignedContext = null;

		try{
			PKCS8EncodedKeySpec privKeySpec=new PKCS8EncodedKeySpec(EncodedprivKey);
			KeyFactory keyFactory=KeyFactory.getInstance("RSA");
			PrivateKey privKey=keyFactory.generatePrivate(privKeySpec);
			Signature rsa=Signature.getInstance("SHA1withRSA");
			rsa.initSign(privKey);
			for (int i=0;i<Context.length;i++)
				rsa.update(Context[i]);
			SignedContext=rsa.sign();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return SignedContext;

	}

	public static boolean VerifySign(String ID, String src, String sign)
	{
		boolean verifies=false;

		try{
			FileInputStream fos = new FileInputStream("PublicKey_"+ID);
	       		byte[] EncodedpubKey = new byte[fos.available()];
	        	fos.read(EncodedpubKey);
	       		fos.close();

	       		byte[] Context = src.getBytes();

	       		byte[] SignedContext = base64dec(sign.getBytes());
			X509EncodedKeySpec pubKeySpec= new X509EncodedKeySpec(EncodedpubKey);
			KeyFactory keyFactory=KeyFactory.getInstance("RSA");
			PublicKey pubKey=keyFactory.generatePublic(pubKeySpec);
			Signature sigObj=Signature.getInstance("SHA1withRSA");
			sigObj.initVerify(pubKey);
			for (int i=0;i<Context.length;i++)
				sigObj.update(Context[i]);
			verifies=sigObj.verify(SignedContext);
			}
		catch(Exception e)
		{
			e.printStackTrace();
			return false;
		}
		return verifies;
	}

	public static boolean VerifySign1(byte[] EncodedpubKey, byte[] Context, byte[] SignedContext)
	{
		boolean verifies=false;

		try{

			X509EncodedKeySpec pubKeySpec= new X509EncodedKeySpec(EncodedpubKey);
			KeyFactory keyFactory=KeyFactory.getInstance("RSA");
			PublicKey pubKey=keyFactory.generatePublic(pubKeySpec);
			Signature sigObj=Signature.getInstance("SHA1withRSA");
			sigObj.initVerify(pubKey);
			for (int i=0;i<Context.length;i++)
				sigObj.update(Context[i]);
			verifies=sigObj.verify(SignedContext);
			}
		catch(Exception e)
		{
			e.printStackTrace();
			return false;
		}
		return verifies;
	}

	public static boolean VerifyET(String ID, String src, String sign)
	{
		boolean verifies=false;
		try{

			FileInputStream fis = new FileInputStream("PubKey_ForJava_"+ID);
			byte[] temp = new byte[fis.available()];
	      		fis.read(temp);
	      		fis.close();

	      		byte[] Context = src.getBytes();

	       		byte[] SignedContext = base64dec(sign.getBytes());

	        	byte[] e = new byte[3];
	        	byte[] m = new byte[temp.length-3];

	        	for(int j = 0;j<3;j++)
	        		e[j] = temp[j];
	        	for(int j = 0;j<temp.length-3;j++)
	        		m[j] = temp[j+3];

	        	verifies = VerifySignET(m,e,Context,SignedContext);
	        }
	        catch(Exception e)
		{
			e.printStackTrace();
			return false;
		}
		return verifies;

	}

	public static boolean VerifyET1(String FileName, byte[] Context, byte[] SignedContext)
	{
		boolean verifies=false;
		try{

			FileInputStream fis = new FileInputStream(FileName);
			byte[] temp = new byte[fis.available()];
	      		fis.read(temp);
	      		fis.close();

	        	byte[] e = new byte[3];
	        	byte[] m = new byte[temp.length-3];

	        	for(int j = 0;j<3;j++)
	        		e[j] = temp[j];
	        	for(int j = 0;j<temp.length-3;j++)
	        		m[j] = temp[j+3];

	        	verifies = VerifySignET(m,e,Context,SignedContext);
	        }
	        catch(Exception e)
		{
			e.printStackTrace();
			return false;
		}
		return verifies;

	}

	public static boolean VerifySignET(byte[] Modulus, byte[] Exponent, byte[] Context, byte[] SignedContext)
	{
		boolean verifies=false;

		try{
			BigInteger m = new BigInteger(Modulus);
	       		BigInteger e = new BigInteger(Exponent);
			RSAPublicKeySpec pubKeySpec= new RSAPublicKeySpec(m,e);
			KeyFactory keyFactory=KeyFactory.getInstance("RSA");
			PublicKey pubKey=keyFactory.generatePublic(pubKeySpec);
			Signature sigObj=Signature.getInstance("SHA1withRSA");
			sigObj.initVerify(pubKey);
			for (int i=0;i<Context.length;i++)
				sigObj.update(Context[i]);
			verifies=sigObj.verify(SignedContext);
			}
		catch(Exception e)
		{
			e.printStackTrace();
			return false;
		}
		return verifies;
	}

	public static String Bytes2HexString(byte[] b)
    	{
    		String ret = "";
    		for (int i = 0; i < b.length; i++) {
      			String hex = Integer.toHexString(b[i] & 0xFF);
      			if (hex.length() == 1) {
        			hex = '0' + hex;
      			}
      			ret += hex.toUpperCase();
    		}
    		return ret;
  	}

    	 public static byte[] HexString2Bytes(String source)
    	 {
    		byte[] ret = new byte[source.length()/2];

    		//System.out.println("str"+source.length());
    		byte[] tmp = source.getBytes();
    		//System.out.println("byte"+tmp.length);
    		for(int i=0; i<((source.length())/2); i++){
     			 ret[i] = Sign.UniteBytes(tmp[i*2], tmp[i*2+1]);
    		}
    		return ret;
  	 }

  	 public static byte UniteBytes(byte s0, byte s1)
  	 {
    		byte b_left4 = Byte.decode("0x" + new String(new byte[]{s0})).byteValue();
    		b_left4 = (byte)(b_left4 << 4);
    		byte b_right4 = Byte.decode("0x" + new String(new byte[]{s1})).byteValue();
    		byte b = (byte)(b_left4 ^ b_right4);
    		return b;
  	}

  	public static byte[] base64enc(byte src[])
    {
        byte result[] = null;
        try
        {
            BASE64Encoder base64 = new BASE64Encoder();
            result = base64.encode(src).getBytes();
        }
        catch(Exception x)
        {
            x.printStackTrace();
            result = null;
        }
        return result;
    }

    public static byte[] base64dec(byte src[])
    {
        byte result[] = null;
           try
            {
                BASE64Decoder base64 = new BASE64Decoder();
                ByteArrayInputStream is = new ByteArrayInputStream(src);
                result = base64.decodeBuffer(is);
            }
            catch(Exception x)
            {
                x.printStackTrace();
                result = null;

            }

            return result;

    }

}